#include "util.hpp"
#include "level.hpp"
#include "message.hpp"
#include "format.hpp"
#include "sink.hpp"
#include "logger.hpp"
#include "buffer.hpp"
#include "logsys.h"
//测试util
// int main() {
//     // 输出当前时间戳，通过调用logsys命名空间下util子命名空间中date类的静态成员函数now()获取时间戳
//     std::cout << logsys::util::date::now() << std::endl; 
//     // 定义一个字符串变量pathname，存储文件路径"./abc/bcd/a.txt"
//     std::string pathname = "./abc/bcd/a.txt"; 
//     // 调用logsys命名空间下util子命名空间中file类的静态成员函数path，获取pathname路径中的目录部分
//     // 再将得到的目录部分作为参数，调用file类的静态成员函数createdirectory来创建目录
//     logsys::util::file::createDirectory(logsys::util::file::path(pathname)); 
//     return 0;
// }

//测试level
// int main(){
//     // 输出DEBUG日志等级对应的字符串表示，通过调用logsys命名空间下LogLevel类的静态函数toString
//     std::cout << logsys::LogLevel::toString(logsys::LogLevel::value::DEBUG) << std::endl;
//     // 输出INFO日志等级对应的字符串表示
//     std::cout << logsys::LogLevel::toString(logsys::LogLevel::value::INFO) << std::endl;
//     // 输出WARN日志等级对应的字符串表示
//     std::cout << logsys::LogLevel::toString(logsys::LogLevel::value::WARN) << std::endl;
//     // 输出ERROR日志等级对应的字符串表示
//     std::cout << logsys::LogLevel::toString(logsys::LogLevel::value::ERROR) << std::endl;
//     // 输出FATAL日志等级对应的字符串表示
//     std::cout << logsys::LogLevel::toString(logsys::LogLevel::value::FATAL) << std::endl;
//     // 输出OFF日志等级对应的字符串表示
//     std::cout << logsys::LogLevel::toString(logsys::LogLevel::value::OFF) << std::endl;
//     return 0;
// }

//测试message和format
// int main() {
//     // 创建一个LogMsg对象，传入日志等级为INFO、行号为53、文件名"main.c"、日志器名"root"、日志消息"格式化功能测试..."
//     logsys::LogMsg msg(logsys::LogLevel::value::INFO, 53, "main.c", "root", "格式化功能测试..."); 
//     // 创建一个Formatter对象，用于对日志消息进行格式化
//     logsys::Formatter fmt; 
//     // 调用Formatter的format函数对LogMsg对象进行格式化，并将结果存储在str中
//     std::string str = fmt.format(msg); 
//     // 输出格式化后的日志消息字符串
//     std::cout << str << std::endl; 
//     return 0;
// }

//测试sink

// int main() {
//     // 创建一个LogMsg对象，设置日志等级为INFO、行号为53、文件名"main.c"、日志器名"root"、日志消息"格式化功能测试..."
//     logsys::LogMsg msg(logsys::LogLevel::value::INFO, 53, "main.c", "root", "格式化功能测试..."); 
//     // 创建一个Formatter对象，传入自定义的格式化模式字符串
//     logsys::Formatter fmt; 
//     // 使用Formatter对象对LogMsg对象进行格式化，得到格式化后的字符串
//     std::string str = fmt.format(msg); 
//     // 使用SinkFactory创建一个指向标准输出落地对象的智能指针
//     logsys::LogSink::ptr stdout_lsp = logsys::SinkFactory::create<logsys::StdoutSink>(); 
//     // 使用SinkFactory创建一个指向文件落地对象的智能指针，指定文件路径为"./logfile/test.log"
//     logsys::LogSink::ptr file_lsp = logsys::SinkFactory::create<logsys::FileSink>("./logfile/test.log"); 
//     // 使用SinkFactory创建一个指向按大小滚动文件落地对象的智能指针，指定基础文件名"./logfile/roll-"和最大文件大小
//     logsys::LogSink::ptr roll_lsp = logsys::SinkFactory::create<logsys::RollBySizeSink>("./logfile/roll-", 1024 * 1024 * 10); 
//     // 将格式化后的日志消息写入标准输出
//     stdout_lsp->log(str.c_str(), str.size()); 
//     // 将格式化后的日志消息写入指定文件
//     file_lsp->log(str.c_str(), str.size()); 
//     size_t cursize = 0;
//     size_t count = 0;
//     // 循环写入日志消息到滚动文件，直到达到指定大小（10MB ）
//     while (cursize < 1024 * 1024 * 10) { 
//         std::string tmp = str + std::to_string(count++);
//         roll_lsp->log(tmp.c_str(), tmp.size());
//         cursize += tmp.size();
//     }
//     return 0;
// }

//尝试扩展 按时间写入
// 扩展一个以时间作为值分隔滚动切换类型的日志落地模块
// 1. 以时间进行滚动，实际上是以时间段进行滚动
// 实现思想：以当前系统时间，取模时间段大小，可以得到当前时间段是第几个时间段
// 每次以当前系统时间取模，判断与当前文件的时间段是否一致，不一致代表不是同一个时间段
// enum class TimeGap {
//     GAP_SECOND,
//     GAP_MINUTE,
//     GAP_HOUR,
//     GAP_DAY
// };

// class RollByTimeSink : public logsys::LogSink {
// public:
//     // 构造时传入文件名，并打开文件，将操作句柄管理起来
//     RollByTimeSink(const std::string &basename, TimeGap gap_type) : _basename(basename) {
//         switch (gap_type) {
//             case TimeGap::GAP_SECOND: _gap_size = 1; break;
//             case TimeGap::GAP_MINUTE: _gap_size = 60; break;
//             case TimeGap::GAP_HOUR: _gap_size = 3600; break;
//             case TimeGap::GAP_DAY: _gap_size = 3600 * 24; break;
//         }
//         // 获取当前是第几个时间段
//         _cur_gap = _gap_size == 1? logsys::util::Date::now() : logsys::util::Date::now() % _gap_size; 
//         std::string filename = createNewFile();
//         logsys::util::File::createDirectory(logsys::util::File::path(filename));
//         _ofs.open(filename, std::ios::binary | std::ios::app);
//         assert(_ofs.is_open());
//     }
//     // 将日志消息写入到标准输出，判断当前时间是否是当前文件的时间段，不是则切换文件
//     void log(const char *data, size_t len) {
//         time_t cur = logsys::util::Date::now();
//         if ((cur % _gap_size) != _cur_gap) {
//             _ofs.close();
//             std::string filename = createNewFile();
//             _ofs.open(filename, std::ios::binary | std::ios::app);
//             assert(_ofs.is_open());
//         }
//         _ofs.write(data, len);
//         assert(_ofs.good());
//     }
// private:
//     std::string createNewFile() {
//         time_t t = logsys::util::Date::now();
//         struct tm lt;
//         localtime_r(&t, &lt);
//         std::stringstream filename;
//         filename << _basename;
//         filename << lt.tm_year + 1900;
//         filename << lt.tm_mon + 1;
//         filename << lt.tm_mday;
//         filename << lt.tm_hour;
//         filename << lt.tm_min;
//         filename << lt.tm_sec;
//         filename << ".log";
//         return filename.str();
//     }
// private:
//     std::string _basename;
//     std::ofstream _ofs;
//     size_t _cur_gap; // 当前是第几个时间段
//     size_t _gap_size; // 时间段的大小
// };
// //测试扩展
// int main(){
//     // 创建一个按时间滚动的日志记录器
//      // 创建一个LogMsg对象，设置日志等级为INFO、行号为53、文件名"main.c"、日志器名"root"、日志消息"格式化功能测试..."
//     logsys::LogMsg msg(logsys::LogLevel::value::INFO, 53, "main.c", "root", "格式化功能测试..."); 
//     // 创建一个Formatter对象，传入自定义的格式化模式字符串
//     logsys::Formatter fmt; 
//     // 使用Formatter对象对LogMsg对象进行格式化，得到格式化后的字符串
//     std::string str = fmt.format(msg); 
//     logsys::LogSink::ptr time_lsp = logsys::SinkFactory::create<RollByTimeSink>("./logfile/roll-", TimeGap::GAP_SECOND);
//     time_t old = logsys::util::Date::now();
//     while (logsys::util::Date::now() < old + 5) {
//     time_lsp->log(str.c_str(), str.size());
//     usleep(1000);
// }
// }

// 测试，同步日志器
// int main() {
//     // 创建一个指向LocalLoggerBuilder的unique_ptr，用于构建日志器
//     std::unique_ptr<logsys::LoggerBuilder> builder(new logsys::LocalLoggerBuilder());
//     // 设置日志器名称为"sync_logger"
//     builder->buildLoggerName("sync_logger");
//     // 设置日志器的日志等级为WARN
//     builder->buildLoggerLevel(logsys::LogLevel::value::WARN);
//     // 设置日志格式化模式为"%m%n"
//     builder->buildFormatter("%m%n");
//     // 设置日志器类型为同步（LOGGER_SYNC ）
//     builder->buildLoggerType(logsys::LoggerType::LOGGER_SYNC);
//     // 添加一个FileSink类型的日志落地模块，指定日志文件路径为"./logfile/test.log"
//     builder->buildSink<logsys::FileSink>("./logfile/test.log");
//     // 添加一个RollBySizeSink类型的日志落地模块，指定基础文件名"./logfile/roll-"和滚动大小为1024 * 1024字节
//     builder->buildSink<logsys::RollBySizeSink>("./logfile/roll-", 1024 * 1024);
//     // 调用build函数构建出日志器对象，并获取其指针
//     logsys::Logger::ptr logger = builder->build();

//     // 使用日志器输出不同等级的日志
//     // DEBUG等级日志，__FILE__表示当前源文件名，__LINE__表示当前行号
//     logger->debug(__FILE__, __LINE__, "%s", "测试日志");
//     // INFO等级日志
//     logger->info(__FILE__, __LINE__, "%s", "测试日志");
//     // WARN等级日志
//     logger->warn(__FILE__, __LINE__, "%s", "测试日志");
//     // ERROR等级日志
//     logger->error(__FILE__, __LINE__, "%s", "测试日志");
//     // FATAL等级日志
//     logger->fatal(__FILE__, __LINE__, "%s", "测试日志");

//     size_t cursize = 0, count = 0;
//     // 循环输出FATAL等级日志，直到写入的日志大小达到10 * 1024 * 1024字节
//     while (cursize < 1024 * 1024 * 10) {
//         // 假设 log 函数返回实际写入的字节数
//        while (cursize < 1024 * 1024 * 10) {
//         logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
//         // 这里可能缺少对cursize的更新逻辑，实际使用中需要正确更新已写入的日志大小
//         cursize += 10; // 这里仅为示意，实际应根据日志内容计算大小
//         usleep(1000); // 休眠1毫秒，模拟日志写入过程
//         // 这里应该有对cursize的更新逻辑，但由于缺少具体实现细节，此处仅为示意
//     }
//     return 0;
//     }
// }

// int main() {
//     // 读取文件数据，一点一点写入缓冲区，最终将缓冲区数据写入文件，判断生成的新文件与源文件是否一致
//     std::ifstream ifs("./logs/test.log", std::ios::binary);
//     // 打开文件失败处理
//     if (ifs.is_open() == false) { 
//         std::cout << "open failed!\n"; 
//         return -1;
//     }
//     ifs.seekg(0, std::ios::end); // 读写位置跳转到文件末尾
//     size_t fsize = ifs.tellg(); // 获取当前读写位置相对于起始位置的偏移量，即文件大小
//     ifs.seekg(0, std::ios::beg); // 重新跳转到起始位置
//     std::string body;
//     body.resize(fsize);
//     ifs.read(&body[0], fsize);
//     // 读取文件内容失败处理
//     if (ifs.good() == false) { 
//         std::cout << "read error\n"; 
//         return -1; 
//     }
//     ifs.close();

//     std::cout << fsize << std::endl;
//     logsys::Buffer buffer;
//     // 将文件内容逐个字符写入缓冲区
//     for(int i = 0; i < body.size(); i++) { 
//         buffer.push(&body[i], 1);
//     }
//     std::cout << buffer.readAbleSize() << std::endl;

//     std::ofstream ofs("./log/tmp.log", std::ios::binary);
//     // 一次性将缓冲区数据写入新文件
//     ofs.write(buffer.begin(), buffer.readAbleSize()); 
//     // if(!ofs.is_open()){std::cout<<"open failed!\n";return -1;}
//     // size_t rsize=buffer.readAbleSize();//获取缓冲区可读数据大小
//     // for(int i=0;i<rsize;++i){
//     //     ofs.write(buffer.begin(),1);//将缓冲区数据写入文件
//     //     if(!ofs.good()){std::cout<<"write failed!\n";return -1;}//判断写入是否成功
//     //     buffer.moveReader(1);//将缓冲区数据弹出
//     // }
//     ofs.close();//关闭文件
//     return 0;
// }

// int main() {
//     // 安全模式
//         std::unique_ptr<logsys::LoggerBuilder> builder(new logsys::LocalLoggerBuilder());
//         builder->buildLoggerName("async_logger");
//         builder->buildLoggerLevel(logsys::LogLevel::value::WARN);
//         builder->buildFormatter("[%c]%m%n");
//         builder->buildLoggerType(logsys::LoggerType::LOGGER_ASYNC);
//         builder->buildSink<logsys::FileSink>("./logfile/async.log");
//         builder->buildSink<logsys::StdoutSink>();
//         logsys::Logger::ptr logger = builder->build();

//         logger->debug(__FILE__, __LINE__, "%s", "测试日志");
//         logger->info(__FILE__, __LINE__, "%s", "测试日志");
//         logger->warn(__FILE__, __LINE__, "%s", "测试日志");
//         logger->error(__FILE__, __LINE__, "%s", "测试日志");
//         logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
//         size_t cursize = 0, count = 0;
//         while (cursize < 1024 * 1024 * 10) {
//             logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
//             cursize += 20;
//         }
//             // 非安全模式
//     //     size_t count = 0;
//     //     while (count < 500000) {
//     //         // 这里假设已经有可用的logger对象，或者在该作用域内有正确的获取方式
//     //         // 目前代码中未体现如何获取合适的logger，以下仅为按原逻辑示意
//     //         logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++); 
//     //     }
//     // 

//         return 0;
//     }


//测试日志管理器和全局
// 管理器测试
// void test_log() {
//     // 从LoggerManager单例中获取名为"async_logger"的日志器指针
//     logsys::Logger::ptr logger = logsys::LoggerManager::getInstance().getLogger("async_logger");
//     // 使用获取到的日志器输出不同级别的测试日志
//     logger->debug(__FILE__, __LINE__, "%s", "测试日志");
//     logger->info(__FILE__, __LINE__, "%s", "测试日志");
//     logger->warn(__FILE__, __LINE__, "%s", "测试日志");
//     logger->error(__FILE__, __LINE__, "%s", "测试日志");
//     logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
//     size_t count = 0;
//     // 循环输出大量的FATAL级别的测试日志
//     while (count < 500000) {
//         logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
//     }
// }

// int main() {
//     // 创建全局日志器建造者对象
//     std::unique_ptr<logsys::LoggerBuilder> builder(new logsys::GlobalLoggerBuilder());
//     // 设置日志器名称为"async_logger"
//     builder->buildLoggerName("async_logger");
//     // 设置日志器等级为WARN
//     builder->buildLoggerLevel(logsys::LogLevel::value::WARN);
//     // 设置日志格式化模式为"[%c]%m%n"
//     builder->buildFormatter("[%c]%m%n");
//     // 设置日志器类型为异步日志器
//     builder->buildLoggerType(logsys::LoggerType::LOGGER_ASYNC);
//     // 开启不安全异步模式（具体功能依实际实现而定）
//     builder->buildEnableUnSafeAsync(); 
//     // 添加文件日志落地模块，指定日志文件路径为"./logfile/async.log"
//     builder->buildSink<logsys::FileSink>("./logfile/async.log");
//     // 添加标准输出日志落地模块
//     builder->buildSink<logsys::StdoutSink>();
//     // 构建日志器，此操作会将构建好的日志器添加到LoggerManager单例中
//     builder->build(); 

//     // 调用测试函数，测试日志器的功能
//     test_log(); 

//     return 0;
// }


//测试全局接口
// 测试函数
// void test_log() {
//     // 从LoggerManager单例中获取名为"async_logger"的日志器指针
//     logsys::Logger::ptr logger = logsys::LoggerManager::getInstance().getLogger("async_logger");
//     // 使用获取到的日志器输出不同级别的测试日志
//     logger->debug("%s", "测试日志");
//     logger->info("%s", "测试日志");
//     logger->warn("%s", "测试日志");
//     logger->error("%s", "测试日志");
//     logger->fatal("%s", "测试日志");
//     size_t count = 0;
//     // 循环输出大量的FATAL级别的测试日志
//     while (count < 500000) {
//         logger->fatal("测试日志-%d", count++);
//     }
// }

// int main() {
//     // 创建全局日志器建造者对象
//     std::unique_ptr<logsys::LoggerBuilder> builder(new logsys::GlobalLoggerBuilder());
//     // 设置日志器名称为"async_logger"
//     builder->buildLoggerName("async_logger");
//     // 设置日志器等级为WARN
//     builder->buildLoggerLevel(logsys::LogLevel::value::WARN);
//     // 设置日志格式化模式为"[%c][%f:%l]%m%n"
//     builder->buildFormatter("[%c][%f:%l]%m%n");
//     // 设置日志器类型为异步日志器
//     builder->buildLoggerType(logsys::LoggerType::LOGGER_ASYNC);
//     // 开启不安全异步模式（具体功能依实际实现而定）
//     builder->buildEnableUnSafeAsync(); 
//     // 添加文件日志落地模块，指定日志文件路径为"./logfile/async.log"
//     builder->buildSink<logsys::FileSink>("./logfile/async.log");
//     // 添加标准输出日志落地模块
//     builder->buildSink<logsys::StdoutSink>();
//     // 构建日志器，此操作会将构建好的日志器添加到LoggerManager单例中
//     builder->build(); 

//     // 调用测试函数，测试日志器的功能
//     test_log(); 

//     return 0;
// }



